package com.anan.builder;

import com.anan.bean.TableInfo;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class BuildUtils {

    public static void create(String projectName){

        createAes(projectName);
        createAnanUtils(projectName);
        createCreateImageCode(projectName);
        createRedisUtils(projectName);
        createResult(projectName);

    }
    private static void createAes(String projectName) {
        String path = System.getProperty("user.dir") + "/" + projectName + "/src/main/java/com/anan/utils";
        File file = new File(path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建 " + path + " 目录失败");
            }
        }
        File beanFile = new File(path, "Aes.java");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {
            out = new FileOutputStream(beanFile);
            outw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            bw = new BufferedWriter(outw);
            bw.write("package com.anan.utils;\n" +
                    "\n" +
                    "import org.apache.commons.lang3.StringUtils;\n" +
                    "\n" +
                    "import javax.crypto.Cipher;\n" +
                    "import javax.crypto.KeyGenerator;\n" +
                    "import javax.crypto.spec.SecretKeySpec;\n" +
                    "import java.math.BigInteger;\n" +
                    "import java.util.Base64;\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "/**\n" +
                    " * @Author: Anan\n" +
                    " * @email: 2328791101@qq.com\n" +
                    " * @project_name: anan-bookkeeping\n" +
                    " * @time: 2023/7/619:52\n" +
                    " */\n" +
                    "\n" +
                    "/**\n" +
                    " * AES的加密和解密\n" +
                    " * @author libo\n" +
                    " */\n" +
                    "public class Aes {\n" +
                    "    //密钥 (需要前端和后端保持一致)\n" +
                    "    private static final String KEY = \"438F7A7B6118427D956690515EEAEF87\";\n" +
                    "    //算法\n" +
                    "    private static final String ALGORITHMSTR = \"AES/ECB/PKCS5Padding\";\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 将byte[]转为各种进制的字符串\n" +
                    "     * @param bytes byte[]\n" +
                    "     * @param radix 可以转换进制的范围，从Character.MIN_RADIX到Character.MAX_RADIX，超出范围后变为10进制\n" +
                    "     * @return 转换后的字符串\n" +
                    "     */\n" +
                    "    public static String binary(byte[] bytes, int radix){\n" +
                    "        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * base 64 encode\n" +
                    "     * @param bytes 待编码的byte[]\n" +
                    "     * @return 编码后的base 64 code\n" +
                    "     */\n" +
                    "    public static String base64Encode(byte[] bytes){\n" +
                    "        return Base64.getEncoder().encodeToString(bytes);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * base 64 decode\n" +
                    "     * @param base64Code 待解码的base 64 code\n" +
                    "     * @return 解码后的byte[]\n" +
                    "     * @throws Exception\n" +
                    "     */\n" +
                    "    public static byte[] base64Decode(String base64Code) throws Exception{\n" +
                    "        return StringUtils.isEmpty(base64Code) ? null : Base64.getDecoder().decode(base64Code);\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * AES加密\n" +
                    "     * @param content 待加密的内容\n" +
                    "     * @param encryptKey 加密密钥\n" +
                    "     * @return 加密后的byte[]\n" +
                    "     * @throws Exception\n" +
                    "     */\n" +
                    "    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {\n" +
                    "        KeyGenerator kgen = KeyGenerator.getInstance(\"AES\");\n" +
                    "        kgen.init(128);\n" +
                    "        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);\n" +
                    "        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), \"AES\"));\n" +
                    "\n" +
                    "        return cipher.doFinal(content.getBytes(\"utf-8\"));\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * AES加密为base 64 code\n" +
                    "     * @param content 待加密的内容\n" +
                    "     * @param encryptKey 加密密钥\n" +
                    "     * @return 加密后的base 64 code\n" +
                    "     * @throws Exception\n" +
                    "     */\n" +
                    "    public static String encrypt(String content, String encryptKey) throws Exception {\n" +
                    "        return base64Encode(aesEncryptToBytes(content, encryptKey));\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * AES解密\n" +
                    "     * @param encryptBytes 待解密的byte[]\n" +
                    "     * @param decryptKey 解密密钥\n" +
                    "     * @return 解密后的String\n" +
                    "     * @throws Exception\n" +
                    "     */\n" +
                    "    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {\n" +
                    "        KeyGenerator kgen = KeyGenerator.getInstance(\"AES\");\n" +
                    "        kgen.init(128);\n" +
                    "\n" +
                    "        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);\n" +
                    "        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), \"AES\"));\n" +
                    "        byte[] decryptBytes = cipher.doFinal(encryptBytes);\n" +
                    "        return new String(decryptBytes);\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 将base 64 code AES解密\n" +
                    "     * @param encryptStr 待解密的base 64 code\n" +
                    "     * @param decryptKey 解密密钥\n" +
                    "     * @return 解密后的string\n" +
                    "     * @throws Exception\n" +
                    "     */\n" +
                    "    public static String decrypt(String encryptStr, String decryptKey) throws Exception {\n" +
                    "        return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 测试\n" +
                    "     */\n" +
                    "    public static void main(String[] args) throws Exception {\n" +
                    "        String content = \"您好\";\n" +
                    "        System.out.println(\"加密前：\" + content);\n" +
                    "        System.out.println(\"加密密钥和解密密钥：\" + KEY);\n" +
                    "        String encrypt = encrypt(content, KEY);\n" +
                    "        System.out.println(\"加密后：\" + encrypt);\n" +
                    "        String decrypt = decrypt(encrypt, KEY);\n" +
                    "        System.out.println(\"解密后：\" + decrypt);\n" +
                    "    }\n" +
                    "}\n" +
                    "\n");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
    private static void createAnanUtils(String projectName) {
        String path = System.getProperty("user.dir") + "/" + projectName + "/src/main/java/com/anan/utils";
        File file = new File(path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建 " + path + " 目录失败");
            }
        }
        File beanFile = new File(path, "AnanUtils.java");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {
            out = new FileOutputStream(beanFile);
            outw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            bw = new BufferedWriter(outw);
            bw.write("package com.anan.utils;\n" +
                    "\n" +
                    "import cn.hutool.extra.mail.MailAccount;\n" +
                    "import cn.hutool.extra.mail.MailUtil;\n" +
                    "import com.anan.exception.BusinessException;\n" +
                    "import org.apache.commons.lang3.RandomStringUtils;\n" +
                    "import org.slf4j.Logger;\n" +
                    "import org.slf4j.LoggerFactory;\n" +
                    "import org.springframework.mail.javamail.JavaMailSender;\n" +
                    "import org.springframework.mail.javamail.MimeMessageHelper;\n" +
                    "\n" +
                    "import javax.annotation.Resource;\n" +
                    "import javax.crypto.Cipher;\n" +
                    "import javax.crypto.spec.SecretKeySpec;\n" +
                    "import javax.mail.internet.MimeMessage;\n" +
                    "import javax.servlet.http.HttpServletResponse;\n" +
                    "import java.io.File;\n" +
                    "import java.io.FileInputStream;\n" +
                    "import java.io.IOException;\n" +
                    "import java.io.OutputStream;\n" +
                    "import java.math.BigInteger;\n" +
                    "import java.nio.charset.StandardCharsets;\n" +
                    "import java.security.MessageDigest;\n" +
                    "import java.util.*;\n" +
                    "\n" +
                    "/**\n" +
                    " * @Author: Anan\n" +
                    " * @email: 2328791101@qq.com\n" +
                    " * @project_name: anan-bookkeeping\n" +
                    " * @time: 2023/6/2916:37\n" +
                    " */\n" +
                    "\n" +
                    "\n" +
                    "public class AnanUtils {\n" +
                    "    private static final Logger logger = LoggerFactory.getLogger(AnanUtils.class);\n" +
                    "\n" +
                    "    private static final String ALGORITHMS = \"AES/ECB/PKCS5Padding\";\n" +
                    "\n" +
                    "    @Resource\n" +
                    "    private JavaMailSender javaMailSender;\n" +
                    "    @Resource\n" +
                    "    RedisUtils<Object> redisUtils;\n" +
                    "\n" +
                    "    public static String MD5Encryption(String source,String key) {\n" +
                    "        // 1.判断 source 是否有效\n" +
                    "        if (source == null || source.length() == 0) {\n" +
                    "            // 2.如果不是有效的字符串抛出异常\n" +
                    "            throw new RuntimeException(\"字符串不可为空\");\n" +
                    "        }\n" +
                    "        try {\n" +
                    "            source = source+key;\n" +
                    "            // 3.获取 MessageDigest 对象\n" +
                    "            String algorithm = \"md5\";\n" +
                    "            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);\n" +
                    "            // 4.获取明文字符串对应的字节数组\n" +
                    "            byte[] input = source.getBytes();\n" +
                    "            //执行加密\n" +
                    "            byte[] output = messageDigest.digest(input);\n" +
                    "            // 6.创建 BigInteger 对象\n" +
                    "            int signum = 1;\n" +
                    "            BigInteger bigInteger = new BigInteger(signum, output);\n" +
                    "            // 7.按照 16 进制将 bigInteger 的值转换为大写字符串\n" +
                    "            int radix = 16;\n" +
                    "            return bigInteger.toString(radix).toUpperCase();\n" +
                    "        } catch (Exception e) {\n" +
                    "            logger.error(e.getMessage());\n" +
                    "            return null;\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     *  打乱顺序\n" +
                    "     * @param str\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public static String DisruptSort(String str){\n" +
                    "        char[] arr =str.toCharArray();\n" +
                    "        Random random=new Random();\n" +
                    "        for (int i = 0; i < arr.length; i++) {\n" +
                    "            int a = random.nextInt(arr.length);\n" +
                    "            char temp = arr[i];\n" +
                    "            arr[i] = arr[a];\n" +
                    "            arr[a] = temp;\n" +
                    "        }\n" +
                    "        return new String(arr);\n" +
                    "    }\n" +
                    "\n" +
                    "    public static void readFile(HttpServletResponse response, String fileName)  {\n" +
                    "\n" +
                    "        response.setContentType(\"application/octet-stream\");\n" +
                    "\n" +
                    "        String projectPath = System.getProperty(\"user.dir\");\n" +
                    "        File filePath = new File(projectPath + \"/file/\");\n" +
                    "        if(!filePath.exists()){\n" +
                    "            boolean mkdirs = filePath.mkdirs();\n" +
                    "            if (!mkdirs) {\n" +
                    "                throw new BusinessException(400, \"文件文件夹创建失败  请联系管理员创建项目file文件夹\");\n" +
                    "            }\n" +
                    "            throw new BusinessException(400,\"文件不存在\");\n" +
                    "        }\n" +
                    "        File file = new File(projectPath + \"/file/\"+fileName);\n" +
                    "        try {\n" +
                    "            FileInputStream fileInputStream = new FileInputStream(file);\n" +
                    "            OutputStream out = response.getOutputStream();\n" +
                    "            byte[] bytes = new byte[1024];\n" +
                    "            int len = 0;\n" +
                    "            while((len = fileInputStream.read(bytes)) !=-1){\n" +
                    "                out.write(bytes, 0, len);\n" +
                    "            }\n" +
                    "            out.flush();\n" +
                    "            out.close();\n" +
                    "            fileInputStream.close();\n" +
                    "        } catch (IOException e) {\n" +
                    "            throw new BusinessException(400,\"文件传输失败 请重试\");\n" +
                    "        }\n" +
                    "\n" +
                    "    }\n" +
                    "\n" +
                    "    public static String emailSend(String toEmail,String msg,File file ){\n" +
                    "\n" +
                    "\n" +
                    "        MailAccount account = new MailAccount();\n" +
                    "        account.setHost(\"smtp.qq.com\");  // 设置邮件服务器的主机名为\"smtp.qq.com\"。这是QQ邮箱的SMTP服务器地址。\n" +
                    "        account.setPort(465);  // 设置邮件服务器的端口号为465。这是QQ邮箱的SMTP服务器端口号。\n" +
                    "        account.setAuth(true);  // 设置邮件服务器需要身份验证。这意味着发送邮件时需要提供正确的用户名和密码。\n" +
                    "        account.setFrom(\"2328791101@qq.com\");  // 设置邮件的发件人地址为\"2328791101@qq.com\"。这是QQ邮箱的邮箱地址。\n" +
                    "        account.setUser(\"2328791101@qq.com\");  // 设置邮件的发件人用户名为\"Anan记账\"。这是邮件发送时显示的发件人名称。\n" +
                    "        account.setPass(\"sjvtcqzfdnlrdjdh\");  // 设置邮件的发件人密码为\"sjvtcqzfdnlrdjdh\"。这是QQ邮箱的授权码，用于身份验证。\n" +
                    "\n" +
                    "        account.setSslEnable(true);  // 使用SSL安全连接\n" +
                    "        //指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字\n" +
                    "        account.setSocketFactoryClass(\"javax.net.ssl.SSLSocketFactory\");\n" +
                    "        //如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true\n" +
                    "        account.setSocketFactoryFallback(true);\n" +
                    "        // 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口456\n" +
                    "        account.setSocketFactoryPort(465);\n" +
                    "\n" +
                    "        String title = \"用户注册验证码\";\n" +
                    "        String html = String.format(\"<h1>【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。</h1>\", msg);;\n" +
                    "\n" +
                    "        if(file==null) {\n" +
                    "            return MailUtil.send(account, toEmail, title, html, false);\n" +
                    "        }else{\n" +
                    "            return MailUtil.send(account, toEmail, title, html, true, file);\n" +
                    "        }\n" +
                    "\n" +
                    "    }\n" +
                    "\n" +
                    "    public boolean sendCheckCode(String email) {\n" +
                    "        try {\n" +
                    "            String code = RandomStringUtils.random(5,false,true);\n" +
                    "            MimeMessage message = javaMailSender.createMimeMessage();\n" +
                    "            MimeMessageHelper helper = new MimeMessageHelper(message, true);\n" +
                    "            //邮件发件人\n" +
                    "            helper.setFrom(\"2328791101@qq.com\");\n" +
                    "            //邮件收件人 1或多个\n" +
                    "            helper.setTo(email);\n" +
                    "            //邮件主题\n" +
                    "            helper.setSubject(\"用户注册验证码\");\n" +
                    "            //邮件内容\n" +
                    "            helper.setText(String.format(\"【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。\", code));\n" +
                    "            //邮件发送时间\n" +
                    "            helper.setSentDate(new Date());\n" +
                    "            // 发送邮件\n" +
                    "            javaMailSender.send(message);\n" +
                    "            logger.info(\"用户 \"+email + \" 的验证码 \"+ code +\" 发送成功！\");\n" +
                    "            redisUtils.put(email, code, 5 * 60L);\n" +
                    "            return true;\n" +
                    "        } catch (Exception e) {\n" +
                    "            logger.error(\"邮件发送失败! error:\", e);\n" +
                    "            throw new BusinessException(\"邮件发送失败\");\n" +
                    "        }\n" +
                    "    }\n" +
                    "    public static boolean stringIsEmpty(Object s) {\n" +
                    "        if(s == null){\n" +
                    "            return true;\n" +
                    "        }\n" +
                    "        String str = s.toString();\n" +
                    "        if (null == str || \"\".equals(str) || \"null\".equals(str) || \"\\u0000\".equals(str)) {\n" +
                    "            return true;\n" +
                    "        } else if (\"\".equals(str.trim())) {\n" +
                    "            return true;\n" +
                    "        }\n" +
                    "        return false;\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 加密\n" +
                    "     *\n" +
                    "     * @param content 内容\n" +
                    "     * @param key     key\n" +
                    "     * @return java.lang.String\n" +
                    "     */\n" +
                    "    public static String encrypt(String content, String key) {\n" +
                    "        try {\n" +
                    "            //获得密码的字节数组\n" +
                    "            byte[] raw = key.getBytes();\n" +
                    "            //根据密码生成AES密钥\n" +
                    "            SecretKeySpec skey = new SecretKeySpec(raw, \"AES\");\n" +
                    "            //根据指定算法ALGORITHM自成密码器\n" +
                    "            Cipher cipher = Cipher.getInstance(ALGORITHMS);\n" +
                    "            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥\n" +
                    "            cipher.init(Cipher.ENCRYPT_MODE, skey);\n" +
                    "            //获取加密内容的字节数组(设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码\n" +
                    "            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);\n" +
                    "            //密码器加密数据\n" +
                    "            byte[] encodeContent = cipher.doFinal(byteContent);\n" +
                    "            //将加密后的数据转换为字符串返回\n" +
                    "\n" +
                    "            return Base64.getEncoder().encodeToString(encodeContent);\n" +
                    "\n" +
                    "        } catch (Exception e) {\n" +
                    "            e.printStackTrace();\n" +
                    "            return null;\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 解密\n" +
                    "     *\n" +
                    "     * @param encryptStr 加密后的内容\n" +
                    "     * @param decryptKey 解密key\n" +
                    "     * @return java.lang.String\n" +
                    "     */\n" +
                    "    public static String decrypt(String encryptStr, String decryptKey) {\n" +
                    "        try {\n" +
                    "            //获得密码的字节数组\n" +
                    "            byte[] raw = decryptKey.getBytes();\n" +
                    "            //根据密码生成AES密钥\n" +
                    "            SecretKeySpec skey = new SecretKeySpec(raw, \"AES\");\n" +
                    "            //根据指定算法ALGORITHM自成密码器\n" +
                    "            Cipher cipher = Cipher.getInstance(ALGORITHMS);\n" +
                    "            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥\n" +
                    "            cipher.init(Cipher.DECRYPT_MODE, skey);\n" +
                    "            //把密文字符串转回密文字节数组\n" +
                    "            byte[] encodeContent = Base64.getDecoder().decode(encryptStr);\n" +
                    "            //密码器解密数据\n" +
                    "            byte[] byteContent = cipher.doFinal(encodeContent);\n" +
                    "            //将解密后的数据转换为字符串返回\n" +
                    "            return new String(byteContent, StandardCharsets.UTF_8);\n" +
                    "        } catch (Exception e) {\n" +
                    "            logger.error(\"String : {} aes decrypt error\", encryptStr);\n" +
                    "            return null;\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "    public static void main(String[] args) {\n" +
                    "//        System.out.println(MD5Encryption(\"root\", \"root\"));\n" +
                    "//        System.out.println(DisruptSort(String.valueOf(System.currentTimeMillis())));\n" +
                    "//        System.out.println(encrypt(\"anan\", \"46053F08D4A8411C825CDF61885265E7\"));\n" +
                    "//        System.out.println(decrypt(\"MvkGW9eGU/tK1Q+PAyeXIg==\", \"46053F08D4A8411C825CDF61885265E7\"));\n" +
                    "\n" +
                    "    }\n" +
                    "}\n");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
    private static void createCreateImageCode(String projectName) {
        String path = System.getProperty("user.dir") + "/" + projectName + "/src/main/java/com/anan/utils";
        File file = new File(path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建 " + path + " 目录失败");
            }
        }
        File beanFile = new File(path, "CreateImageCode.java");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {
            out = new FileOutputStream(beanFile);
            outw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            bw = new BufferedWriter(outw);
            bw.write("package com.anan.utils;\n" +
                    "\n" +
                    "import org.apache.commons.lang3.RandomStringUtils;\n" +
                    "\n" +
                    "import javax.imageio.ImageIO;\n" +
                    "import java.awt.*;\n" +
                    "import java.awt.image.BufferedImage;\n" +
                    "import java.io.IOException;\n" +
                    "import java.io.OutputStream;\n" +
                    "import java.util.Random;\n" +
                    "\n" +
                    "public class CreateImageCode {\n" +
                    "    // 图片的宽度。\n" +
                    "    private int width = 160;\n" +
                    "    // 图片的高度。\n" +
                    "    private int height = 40;\n" +
                    "    // 验证码字符个数\n" +
                    "    private int codeCount = 5;\n" +
                    "    // 验证码干扰线数\n" +
                    "    private int lineCount = 15;\n" +
                    "    // 验证码\n" +
                    "    private String code = null;\n" +
                    "    // 验证码图片Buffer\n" +
                    "    private BufferedImage buffImg = null;\n" +
                    "    Random random = new Random();\n" +
                    "\n" +
                    "    public CreateImageCode() {\n" +
                    "        creatImage();\n" +
                    "    }\n" +
                    "\n" +
                    "    public CreateImageCode(int width, int height) {\n" +
                    "        this.width = width;\n" +
                    "        this.height = height;\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    // 生成图片\n" +
                    "    private void creatImage() {\n" +
                    "        int fontWidth = width / codeCount;// 字体的宽度\n" +
                    "        int fontHeight = height - 5;// 字体的高度\n" +
                    "        int codeY = height - 8;\n" +
                    "\n" +
                    "        // 图像buffer\n" +
                    "        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\n" +
                    "        Graphics g = buffImg.getGraphics();\n" +
                    "        //Graphics2D g = buffImg.createGraphics();\n" +
                    "        // 设置背景色\n" +
                    "        g.setColor(getRandColor(200, 250));\n" +
                    "        g.fillRect(0, 0, width, height);\n" +
                    "        // 设置字体\n" +
                    "        Font font = getFont(fontHeight);\n" +
                    "//        Font font = new Font(\"Fixedsys\", Font.BOLD, fontHeight);\n" +
                    "        g.setFont(font);\n" +
                    "\n" +
                    "        // 设置干扰线\n" +
                    "        for (int i = 0; i < lineCount; i++) {\n" +
                    "            int xs = random.nextInt(width);\n" +
                    "            int ys = random.nextInt(height);\n" +
                    "            int xe = xs + random.nextInt(width);\n" +
                    "            int ye = ys + random.nextInt(height);\n" +
                    "            g.setColor(getRandColor(1, 255));\n" +
                    "            g.drawLine(xs, ys, xe, ye);\n" +
                    "        }\n" +
                    "\n" +
                    "        // 添加噪点\n" +
                    "        float yawpRate = 0.01f;// 噪声率\n" +
                    "        int area = (int) (yawpRate * width * height);\n" +
                    "        for (int i = 0; i < area; i++) {\n" +
                    "            int x = random.nextInt(width);\n" +
                    "            int y = random.nextInt(height);\n" +
                    "            buffImg.setRGB(x, y, random.nextInt(255));\n" +
                    "        }\n" +
                    "\n" +
                    "        String str1 = randomStr(codeCount);// 得到随机字符\n" +
                    "        this.code = str1;\n" +
                    "        for (int i = 0; i < codeCount; i++) {\n" +
                    "            String strRand = str1.substring(i, i + 1);\n" +
                    "            g.setColor(getRandColor(1, 255));\n" +
                    "            // g.drawString(a,x,y);\n" +
                    "            // a为要画出来的东西，x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处\n" +
                    "\n" +
                    "            g.drawString(strRand, i * fontWidth + 3, codeY);\n" +
                    "        }\n" +
                    "    }\n" +
                    "\n" +
                    "    // 得到随机字符\n" +
                    "    private String randomStr(int n) {\n" +
                    "        String str1 = \"ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz123456789\";\n" +
                    "        StringBuilder str2 = new StringBuilder();\n" +
                    "        int len = str1.length() - 1;\n" +
                    "        double r;\n" +
                    "        for (int i = 0; i < n; i++) {\n" +
                    "            r = (Math.random()) * len;\n" +
                    "            str2.append(str1.charAt((int) r));\n" +
                    "        }\n" +
                    "        return str2.toString();\n" +
                    "//        return RandomStringUtils.random(codeCount,true,true);\n" +
                    "    }\n" +
                    "\n" +
                    "    // 得到随机颜色\n" +
                    "    private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色\n" +
                    "        if (fc > 255) fc = 255;\n" +
                    "        if (bc > 255) bc = 255;\n" +
                    "        int r = fc + random.nextInt(bc - fc);\n" +
                    "        int g = fc + random.nextInt(bc - fc);\n" +
                    "        int b = fc + random.nextInt(bc - fc);\n" +
                    "        return new Color(r, g, b);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 产生随机字体\n" +
                    "     */\n" +
                    "    private Font getFont(int size) {\n" +
                    "        Random random = new Random();\n" +
                    "        Font font[] = new Font[6];\n" +
                    "        font[0] = new Font(\"Ravie\", Font.PLAIN, size);\n" +
                    "        font[1] = new Font(\"Antique Olive Compact\", Font.PLAIN, size);\n" +
                    "        font[2] = new Font(\"Fixedsys\", Font.PLAIN, size);\n" +
                    "        font[3] = new Font(\"Wide Latin\", Font.PLAIN, size);\n" +
                    "        font[4] = new Font(\"Gill Sans Ultra Bold\", Font.PLAIN, size);\n" +
                    "        font[5] = new Font(\"Fixedsys\", Font.BOLD, size);\n" +
                    "        return font[random.nextInt(6)];\n" +
                    "    }\n" +
                    "\n" +
                    "    // 扭曲方法\n" +
                    "    private void shear(Graphics g, int w1, int h1, Color color) {\n" +
                    "        shearX(g, w1, h1, color);\n" +
                    "        shearY(g, w1, h1, color);\n" +
                    "    }\n" +
                    "\n" +
                    "    private void shearX(Graphics g, int w1, int h1, Color color) {\n" +
                    "\n" +
                    "        int period = random.nextInt(2);\n" +
                    "\n" +
                    "        boolean borderGap = true;\n" +
                    "        int frames = 1;\n" +
                    "        int phase = random.nextInt(2);\n" +
                    "\n" +
                    "        for (int i = 0; i < h1; i++) {\n" +
                    "            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);\n" +
                    "            g.copyArea(0, i, w1, 1, (int) d, 0);\n" +
                    "            if (borderGap) {\n" +
                    "                g.setColor(color);\n" +
                    "                g.drawLine((int) d, i, 0, i);\n" +
                    "                g.drawLine((int) d + w1, i, w1, i);\n" +
                    "            }\n" +
                    "        }\n" +
                    "\n" +
                    "    }\n" +
                    "\n" +
                    "    private void shearY(Graphics g, int w1, int h1, Color color) {\n" +
                    "\n" +
                    "        int period = random.nextInt(40) + 10; // 50;\n" +
                    "\n" +
                    "        boolean borderGap = true;\n" +
                    "        int frames = 20;\n" +
                    "        int phase = 7;\n" +
                    "        for (int i = 0; i < w1; i++) {\n" +
                    "            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);\n" +
                    "            g.copyArea(i, 0, 1, h1, 0, (int) d);\n" +
                    "            if (borderGap) {\n" +
                    "                g.setColor(color);\n" +
                    "                g.drawLine(i, (int) d, i, 0);\n" +
                    "                g.drawLine(i, (int) d + h1, i, h1);\n" +
                    "            }\n" +
                    "\n" +
                    "        }\n" +
                    "\n" +
                    "    }\n" +
                    "\n" +
                    "    public void write(OutputStream sos) throws IOException {\n" +
                    "        ImageIO.write(buffImg, \"png\", sos);\n" +
                    "        sos.close();\n" +
                    "    }\n" +
                    "\n" +
                    "    public BufferedImage getBuffImg() {\n" +
                    "        return buffImg;\n" +
                    "    }\n" +
                    "\n" +
                    "    public String getCode() {\n" +
                    "        return code.toLowerCase();\n" +
                    "    }\n" +
                    "}\n");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
    private static void createRedisUtils(String projectName) {
        String path = System.getProperty("user.dir") + "/" + projectName + "/src/main/java/com/anan/utils";
        File file = new File(path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建 " + path + " 目录失败");
            }
        }
        File beanFile = new File(path, "RedisUtils.java");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {
            out = new FileOutputStream(beanFile);
            outw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            bw = new BufferedWriter(outw);
            bw.write("package com.anan.utils;\n" +
                    "\n" +
                    "\n" +
                    "import org.springframework.data.redis.core.Cursor;\n" +
                    "import org.springframework.data.redis.core.RedisTemplate;\n" +
                    "import org.springframework.data.redis.core.ScanOptions;\n" +
                    "import org.springframework.data.redis.core.ZSetOperations;\n" +
                    "import org.springframework.stereotype.Component;\n" +
                    "\n" +
                    "import javax.annotation.Resource;\n" +
                    "import java.time.Duration;\n" +
                    "import java.util.*;\n" +
                    "import java.util.concurrent.TimeUnit;\n" +
                    "\n" +
                    "@Component(\"redisUtils\")\n" +
                    "public class RedisUtils<T> {\n" +
                    "\n" +
                    "    @Resource\n" +
                    "    private   RedisTemplate<String, Object> redisTemplate;\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 判断缓存是否存在\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return 缓存是否存在\n" +
                    "     */\n" +
                    "    public  Boolean hasKey(String key){\n" +
                    "        return redisTemplate.hasKey(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 缓存数据\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param value 缓存值\n" +
                    "     */\n" +
                    "    public  void put(String key, Object value){\n" +
                    "        redisTemplate.opsForValue().set(key, value);\n" +
                    "    }\n" +
                    "    /**\n" +
                    "     * 缓存数据\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param value 缓存值\n" +
                    "     * @param timeout 缓存失效时间，单位：秒\n" +
                    "     */\n" +
                    "    public  void put(String key, Object value, Long timeout){\n" +
                    "        put(key, value, Duration.ofSeconds(timeout));\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 缓存数据\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param value 缓存值\n" +
                    "     * @param timeout 缓存失效时间，单位：秒\n" +
                    "     */\n" +
                    "    public  void put(String key, Object value, Duration timeout){\n" +
                    "        redisTemplate.opsForValue().set(key, value, timeout);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取缓存\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return 缓存值\n" +
                    "     */\n" +
                    "    public  Object get(String key) {\n" +
                    "        return redisTemplate.opsForValue().get(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 缓存失效时间设置\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param timeout 失效时间 ,单位s\n" +
                    "     */\n" +
                    "    public  void expire(String key, Long timeout) {\n" +
                    "        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 缓存失效时间设置\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param date 失效时间\n" +
                    "     */\n" +
                    "    public  void expireAt(String key, Date date) {\n" +
                    "        redisTemplate.expireAt(key, date);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 删除缓存\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return 是否删除成功\n" +
                    "     */\n" +
                    "    public  Boolean delete(String key) {\n" +
                    "        return redisTemplate.delete(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 往hash中添加字段和值\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param field hash表中的key\n" +
                    "     * @param value hash表中的value\n" +
                    "     */\n" +
                    "    public  void hashSet(String key, String field, Object value) {\n" +
                    "        redisTemplate.opsForHash().put(key, field, value);\n" +
                    "    }\n" +
                    "    /**\n" +
                    "     * 获取hash中field字段的值\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param field hash表中的key\n" +
                    "     * @return hash表中的value\n" +
                    "     */\n" +
                    "    public  Object hashGet(String key, String field) {\n" +
                    "        return redisTemplate.opsForHash().get(key, field);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取hash表\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Map<Object, Object> entries(String key) {\n" +
                    "        return redisTemplate.opsForHash().entries(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取hash中所有的field\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Set<Object> hashKeys(String key) {\n" +
                    "        return redisTemplate.opsForHash().keys(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取hash中所有的value\n" +
                    "     * @param key 缓存key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  List<Object> hashValues(String key) {\n" +
                    "        return redisTemplate.opsForHash().values(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 该hash中是否存在field\n" +
                    "     * @param key\n" +
                    "     * @param field\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  boolean hasKey(String key, String field){\n" +
                    "        return redisTemplate.opsForHash().hasKey(key, field);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取hash key 中指定的field的值\n" +
                    "     * @param key\n" +
                    "     * @param fieldList\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  List<Object> hashMultiGet(String key, Collection<Object> fieldList){\n" +
                    "        return redisTemplate.opsForHash().multiGet(key, fieldList);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 迭代hash 指定条件的field\n" +
                    "     * @param key\n" +
                    "     * @param options\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Cursor<Map.Entry<Object, Object>> hScan(String key, ScanOptions options){\n" +
                    "        return redisTemplate.opsForHash().scan(key, options);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 删除多个缓存\n" +
                    "     * @param keys\n" +
                    "     * @return 成功删除数量\n" +
                    "     */\n" +
                    "    public  Long delete(List<String> keys) {\n" +
                    "        return redisTemplate.delete(keys);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 删除hash中field缓存\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param fields hash表的key列表\n" +
                    "     * @return 成功删除数量\n" +
                    "     */\n" +
                    "    public  Long hashDelete(String key, List<String> fields) {\n" +
                    "        return redisTemplate.opsForHash().delete(key, fields.toArray());\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 计数器加1\n" +
                    "     * @param key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long increment(String key) {\n" +
                    "        return redisTemplate.opsForValue().increment(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 计数器以指定步长递增\n" +
                    "     * @param key 计数器key\n" +
                    "     * @param delta 自增步长\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long increment(String key, long delta){\n" +
                    "        return redisTemplate.opsForValue().increment(key, delta);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 计数器以指定步长递增\n" +
                    "     * @param key 计数器key\n" +
                    "     * @param delta 自增步长\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Double increment(String key, double delta){\n" +
                    "        return redisTemplate.opsForValue().increment(key, delta);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * hash中field对应计数器加值\n" +
                    "     * @param key\n" +
                    "     * @param field\n" +
                    "     * @param delta\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long hashIncrement(String key, String field, long delta) {\n" +
                    "        return redisTemplate.opsForHash().increment(key, field, delta);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 计数器减1\n" +
                    "     * @param key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long decrement(String key) {\n" +
                    "        return redisTemplate.opsForValue().decrement(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 计数器以指定步长递减\n" +
                    "     * @param key 计数器key\n" +
                    "     * @param delta 递减步长\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long decrement(String key, long delta){\n" +
                    "        return redisTemplate.opsForValue().decrement(key, delta);\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 从队列右边移除一个元素并返回该元素\n" +
                    "     * @author zhanglihui\n" +
                    "     * @date 2020-11-06 10:42\n" +
                    "     * @param key\n" +
                    "     * @return java.lang.Object\n" +
                    "     */\n" +
                    "    public  Object rightPop(String key){\n" +
                    "        return redisTemplate.opsForList().rightPop(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 往列表尾部插入一个元素\n" +
                    "     * @param key\n" +
                    "     * @param value\n" +
                    "     */\n" +
                    "    public  void rightPush(String key, Object value) {\n" +
                    "        redisTemplate.opsForList().rightPush(key, value);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 从队列尾部插入多个元素\n" +
                    "     * @param key  键值\n" +
                    "     * @param values  插入元素列表\n" +
                    "     * @return 插入个数\n" +
                    "     */\n" +
                    "    public  Long rightPushAll(String key, Object... values){\n" +
                    "        return redisTemplate.opsForList().rightPushAll(key, values);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 移除并获取列表头部第一个元素\n" +
                    "     * @param key\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Object leftPop(String key) {\n" +
                    "        return redisTemplate.opsForList().leftPop(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 从队列左边插入一个元素\n" +
                    "     * @author zhanglihui\n" +
                    "     * @date 2020-11-06 10:42\n" +
                    "     * @param key 键值\n" +
                    "     * @param value 插入元素\n" +
                    "     * @return 插入个数\n" +
                    "     */\n" +
                    "    public  Long leftPush(String key, Object value){\n" +
                    "        return redisTemplate.opsForList().leftPush(key, value);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 从队列左边插入多个元素\n" +
                    "     * @param key  键值\n" +
                    "     * @param values  插入元素列表\n" +
                    "     * @return 插入个数\n" +
                    "     */\n" +
                    "    public  Long leftPushAll(String key, Object... values){\n" +
                    "        return redisTemplate.opsForList().leftPushAll(key, values);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取列表长度\n" +
                    "     * @author zhanglihui\n" +
                    "     * @date 2020-11-06 10:46\n" +
                    "     * @param key\n" +
                    "     * @return java.lang.Long\n" +
                    "     */\n" +
                    "    public  Long listSize(String key){\n" +
                    "        return redisTemplate.opsForList().size(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取列表中的数据\n" +
                    "     * @author zhanglihui\n" +
                    "     * @date 2020-11-06 10:47\n" +
                    "     * @param key 缓存值\n" +
                    "     * @param start list开始下标\n" +
                    "     * @param end list结束下标，-1代表末尾\n" +
                    "     * @return java.util.List<java.lang.Object>\n" +
                    "     */\n" +
                    "    public  List<Object> listRange(String key, int start, int end){\n" +
                    "        return redisTemplate.opsForList().range(key, start, end);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 保留指定区间内元素，其余元素都将被删除\n" +
                    "     * @param key list key\n" +
                    "     * @param start 开始下标\n" +
                    "     * @param end 结束下标\n" +
                    "     */\n" +
                    "    public  void listTrim(String key, int start, int end){\n" +
                    "        redisTemplate.opsForList().trim(key,start,end);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 批量查询\n" +
                    "     * @param keys 查询主键列表\n" +
                    "     */\n" +
                    "    public  List<Object> multiGet(List<String> keys) {\n" +
                    "        return redisTemplate.opsForValue().multiGet(keys);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 将member元素添加到有序集key中，按score排序\n" +
                    "     * @param key 有序集\n" +
                    "     * @param member 有续集的成员\n" +
                    "     * @param score 有序集的排序值\n" +
                    "     * @return 是否添加成功\n" +
                    "     */\n" +
                    "    public  Boolean zAdd(String key, Object member, double score){\n" +
                    "        return redisTemplate.opsForZSet().add(key, member, score);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 批量添加元素到有序集key中\n" +
                    "     * @param key 有序集\n" +
                    "     * @param tuples 元素列表\n" +
                    "     * @return 添加数量\n" +
                    "     */\n" +
                    "    public  Long zAdd(String key, Set<ZSetOperations.TypedTuple<Object>> tuples){\n" +
                    "        return redisTemplate.opsForZSet().add(key, tuples);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 返回有序集 key 中，指定区间内的成员。\n" +
                    "     * @param key 有序集\n" +
                    "     * @param start 下标起始位置，从0开始\n" +
                    "     * @param end 下标结束位置，-1表示最后一个\n" +
                    "     * @return 有序集列表\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zRange(String key, long start, long end){\n" +
                    "        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据设置的score获取区间值\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score起始值\n" +
                    "     * @param max score结束值\n" +
                    "     * @return 有序区间值\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zRangeByScore(String key, double min, double max){\n" +
                    "        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据设置的score获取区间值\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score起始值\n" +
                    "     * @param max score结束值\n" +
                    "     * @param offset 偏移值\n" +
                    "     * @param count 返回数量\n" +
                    "     * @return 有序区间值\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zRangeByScore(String key, double min, double max, int offset, int count){\n" +
                    "        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, offset, count);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 移除有序集 key 中，所有 score 值介于 min 和 max 之间\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score最小值\n" +
                    "     * @param max score最大值\n" +
                    "     * @return 删除条数\n" +
                    "     */\n" +
                    "    public  Long removeByScore(String key, double min, double max){\n" +
                    "        return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 删除zset中的某个元素\n" +
                    "     * @param key 有序集\n" +
                    "     * @param values 元素\n" +
                    "     * @return 删除条数\n" +
                    "     */\n" +
                    "    public  Long zSetRemove(String key, Object... values){\n" +
                    "        return redisTemplate.opsForZSet().remove(key, values);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据score范围查询元素，倒序排序\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score最小值\n" +
                    "     * @param max score最大值\n" +
                    "     * @param offset 偏移量\n" +
                    "     * @param count  返回数量\n" +
                    "     * @return Set<ZSetOperations.TypedTuple<Object>>\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zReverseRangeByScoreWithScores(String key, double min, double max, long offset, long count){\n" +
                    "        return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max, offset, count);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据score范围查询元素，倒序排序\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score最小值\n" +
                    "     * @param max score最大值\n" +
                    "     * @return Set<ZSetOperations.TypedTuple<Object>>\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zReverseRangeByScoreWithScores(String key, double min, double max){\n" +
                    "        return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * zset根据下标倒序查询\n" +
                    "     * @param key 缓存key\n" +
                    "     * @param start 开始下标\n" +
                    "     * @param end 结束下标\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Set<ZSetOperations.TypedTuple<Object>> zReverseRangeByScore(String key, long start, long end){\n" +
                    "        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取元素的分值\n" +
                    "     * @param key 有序集\n" +
                    "     * @param value 元素\n" +
                    "     * @return 分值\n" +
                    "     */\n" +
                    "    public  Double score(String key, Object value){\n" +
                    "        return redisTemplate.opsForZSet().score(key, value);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 指定元素增加score\n" +
                    "     * @param key 有序集\n" +
                    "     * @param value 元素\n" +
                    "     * @param delta 增加值\n" +
                    "     * @return score\n" +
                    "     */\n" +
                    "    public  Double incrementScore(String key, Object value, double delta){\n" +
                    "        return redisTemplate.opsForZSet().incrementScore(key, value, delta);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 查询zset大小\n" +
                    "     * @param key 有序集\n" +
                    "     * @return zset元素数量\n" +
                    "     */\n" +
                    "    public  Long zSize(String key){\n" +
                    "        return redisTemplate.opsForZSet().size(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据score范围查询数量\n" +
                    "     * @param key 有序集\n" +
                    "     * @param min score最小值\n" +
                    "     * @param max score最大值\n" +
                    "     * @return 统计数量\n" +
                    "     */\n" +
                    "    public  Long zCount(String key, double min, double max){\n" +
                    "        return redisTemplate.opsForZSet().count(key, min, max);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 根据参数 count 的值，移除列表中与参数 delta 相等的元素。\n" +
                    "     * @param key 队列\n" +
                    "     * @param count\n" +
                    "     * count > 0 : 从表头开始向表尾搜索，移除与 VALUE 相等的元素，数量为 COUNT 。\n" +
                    "     * count < 0 : 从表尾开始向表头搜索，移除与 VALUE 相等的元素，数量为 COUNT 的绝对值。\n" +
                    "     * count = 0 : 移除表中所有与 VALUE 相等的值。\n" +
                    "     * @param value 元素\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public  Long listRem (String key, long count, Object value){\n" +
                    "        return redisTemplate.opsForList().remove(key, count, value);\n" +
                    "    }\n" +
                    "\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 移除有序集中，指定排名(rank)区间内的所有成员。\n" +
                    "     * @param key key\n" +
                    "     * @param start 排名开始位置\n" +
                    "     * @param end 排名结束位置\n" +
                    "     * @return 被移除成员的数量\n" +
                    "     */\n" +
                    "    public  Long zRemByRank(String key, long start, long end){\n" +
                    "        return redisTemplate.opsForZSet().removeRange(key, start, end);\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 返回哈希表中，所有的字段和值\n" +
                    "     * @param key key\n" +
                    "     * @return 所有的字段和值\n" +
                    "     */\n" +
                    "    public  Map<Object,Object> hashAll(String key){\n" +
                    "        return redisTemplate.opsForHash().entries(key);\n" +
                    "    }\n" +
                    "}");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
    private static void createResult(String projectName) {
        String path = System.getProperty("user.dir") + "/" + projectName + "/src/main/java/com/anan/utils";
        File file = new File(path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建 " + path + " 目录失败");
            }
        }
        File beanFile = new File(path, "Result.java");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {
            out = new FileOutputStream(beanFile);
            outw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            bw = new BufferedWriter(outw);
            bw.write("package com.anan.utils;\n" +
                    "\n" +
                    "\n" +
                    "/**\n" +
                    " * @Author: Painter\n" +
                    " * @project_name: springboot_vue\n" +
                    " * @system_login: sunshine\n" +
                    " * @time: 2022/11/114:13\n" +
                    " */\n" +
                    "\n" +
                    "\n" +
                    "public class Result {\n" +
                    "    private Integer code;\n" +
                    "    private String msg;\n" +
                    "    private Object data;\n" +
                    "\n" +
                    "    public Integer getCode() {\n" +
                    "        return code;\n" +
                    "    }\n" +
                    "\n" +
                    "    public void setCode(Integer code) {\n" +
                    "        this.code = code;\n" +
                    "    }\n" +
                    "\n" +
                    "    public String getMsg() {\n" +
                    "        return msg;\n" +
                    "    }\n" +
                    "\n" +
                    "    public void setMsg(String msg) {\n" +
                    "        this.msg = msg;\n" +
                    "    }\n" +
                    "\n" +
                    "    public Object getData() {\n" +
                    "        return data;\n" +
                    "    }\n" +
                    "\n" +
                    "    public void setData(Object data) {\n" +
                    "        this.data = data;\n" +
                    "    }\n" +
                    "\n" +
                    "    @Override\n" +
                    "    public String toString() {\n" +
                    "        return \"Result{\" +\n" +
                    "                \"code=\" + code +\n" +
                    "                \", msg='\" + msg + '\\'' +\n" +
                    "                \", data=\" + data +\n" +
                    "                '}';\n" +
                    "    }\n" +
                    "}\n");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}
